﻿using System;
using System.Data.Common;
using System.Text;
using STPlatform.UPracticalMSSQLDatabaseV2;

namespace SimpleORM
{
    public class SqlFactory : ScriptFactory
    {
        #region Fields

        private const string stringSELECT = "SELECT";
        private const string stringFROM = "FROM";
        private const string stringWHERE = "WHERE";
        private const string stringLIKE = "LIKE";
        private const string stringAND = "AND";
        private const string stringOR = "OR";
        private const string stringIS = "IS";
        private const string stringNULL = "NULL";
        private const string stringNOT = "NOT";
        protected const string stringORDERBY = "ORDER BY";
        protected const string stringASC = "ASC";
        protected const string stringDEC = "DESC";
        private const string stringJOIN = "INNER JOIN";
        private const string stringJOINLEFT = "LEFT JOIN";
        private const string stringON = "ON";
        private const string stringAS = "AS";
        private const string stringGroupBy = "GROUP BY";
        private const string stringINSERT = "INSERT";
        private const string stringINTO = "INTO";
        private const string stringVALUES = "VALUES";
        private const string stringDELETE = "DELETE";
        private const string stringUPADTE = "UPDATE";
        private const string stringSET = "SET";

        #endregion

        #region Methods

        #region Methods - Script

        #region Methods - Script - Format

        protected virtual string FormatFieldName(string fieldName)
        {
            return string.Format("[{0}]", fieldName);
        }

        public override IScriptFactory Stress()
        {
            IScriptFactory f = Clone() as IScriptFactory;
            f.CommandText.Insert(0, '[');
            f.CommandText.Append(']');

            return f;
        }

        #endregion

        #region Methods - Script - Select

        public override IScriptFactory Select()
        {
            IScriptFactory f = New();
            f.CommandText.Append(stringSELECT);
            f.CommandText.Append(" *");
            f.ExecuteArgument = eDbExecuteType.Reader;
            f.Type = eCommandType.Query;

            return f;
        }

        public override IScriptFactory Select(IScriptFactory exp)
        {
            if (exp == null)
                return this;

            IScriptFactory f = New();
            f.CommandText.Append(stringSELECT);
            f.CommandText.Append(' ');
            f.CommandText.Append(exp.CommandText);
            f.ExecuteArgument = eDbExecuteType.Reader;
            f.Parameters.AddRange(exp.Parameters);
            f.Type = eCommandType.Query;

            return f;
        }

        public override IScriptFactory Distinct(IScriptFactory exp)
        {
            if (exp == null)
                return this;

            IScriptFactory f = New();
            f.CommandText.Append("DISTINCT ");
            f.CommandText.Append(exp.CommandText);
            f.Parameters.AddRange(exp.Parameters);

            return f;
        }

        public override IScriptFactory Take(IScriptFactory exp)
        {
            if (exp == null)
                return this;

            IScriptFactory f = New();
            f.CommandText.Append("TOP ");
            f.CommandText.Append(exp.CommandText);
            f.Parameters.AddRange(exp.Parameters);

            return f;
        }

        public override IScriptFactory Count()
        {
            return Count(Constant(0));
        }

        public override IScriptFactory Count(IScriptFactory exp)
        {
            if (exp == null)
                return this;

            IScriptFactory f = New();
            f.CommandText.Append("COUNT(");
            f.CommandText.Append(exp.CommandText);
            f.CommandText.Append(')');

            f = Select(f);
            f.ExecuteArgument = eDbExecuteType.Scalar;
            f.Parameters.AddRange(exp.Parameters);

            return f;
        }

        public override IScriptFactory Average(IScriptFactory exp)
        {
            if (exp == null)
                return this;

            IScriptFactory f = New();
            f.CommandText.Append("AVG(");
            f.CommandText.Append(exp.CommandText);
            f.CommandText.Append(')');

            f = Select(f);
            f.ExecuteArgument = eDbExecuteType.Scalar;
            f.Parameters.AddRange(exp.Parameters);

            return f;
        }

        public override IScriptFactory Sum(IScriptFactory exp)
        {
            if (exp == null)
                return this;

            IScriptFactory f = New();
            f.CommandText.Append("SUM(");
            f.CommandText.Append(exp.CommandText);
            f.CommandText.Append(')');

            f = Select(f);
            f.ExecuteArgument = eDbExecuteType.Scalar;
            f.Parameters.AddRange(exp.Parameters);

            return f;
        }

        public override IScriptFactory Max(IScriptFactory exp)
        {
            if (exp == null)
                return this;

            IScriptFactory f = New();
            f.CommandText.Append("MAX(");
            f.CommandText.Append(exp.CommandText);
            f.CommandText.Append(')');

            f = Select(f);
            f.ExecuteArgument = eDbExecuteType.Scalar;
            f.Parameters.AddRange(exp.Parameters);

            return f;
        }

        public override IScriptFactory Min(IScriptFactory exp)
        {
            if (exp == null)
                return this;

            IScriptFactory f = New();
            f.CommandText.Append("MIN(");
            f.CommandText.Append(exp.CommandText);
            f.CommandText.Append(')');

            f = Select(f);
            f.ExecuteArgument = eDbExecuteType.Scalar;
            f.Parameters.AddRange(exp.Parameters);

            return f;
        }

        public override IScriptFactory As(IScriptFactory exp)
        {
            if (exp == null)
                return this;

            IScriptFactory f = Clone() as IScriptFactory;
            f.CommandText.Append(' ');
            f.CommandText.Append(stringAS);
            f.CommandText.Append(' ');
            f.CommandText.Append(exp.CommandText);
            f.Parameters.AddRange(exp.Parameters);

            return f;
        }

        public override IScriptFactory Len(IScriptFactory exp)
        {
            if (exp == null)
                return this;

            IScriptFactory f = New();
            f.CommandText.Append("LEN(");
            f.CommandText.Append(exp.CommandText);
            f.CommandText.Append(')');
            f.Parameters.AddRange(exp.Parameters);

            return f;
        }

        #endregion

        #region Methods - Script - From

        public override IScriptFactory From(IScriptFactory exp)
        {
            if (exp == null)
                return this;

            IScriptFactory f = New();
            f.CommandText.Append(stringFROM);
            f.CommandText.Append(' ');
            f.CommandText.Append(exp.CommandText);
            f.Parameters.AddRange(exp.Parameters);

            return f;
        }

        #endregion

        #region Methods - Script - Where

        public override IScriptFactory Where(IScriptFactory exp)
        {
            if (exp == null)
                return this;

            IScriptFactory f = New();
            f.CommandText.Append(stringWHERE);
            f.CommandText.Append(' ');
            f.CommandText.Append(exp.CommandText);
            f.Parameters.AddRange(exp.Parameters);

            return f;
        }

        #endregion

        #region Methods - Script - OrderBy

        public override IScriptFactory Ascending(IScriptFactory exp)
        {
            if (exp == null)
                return this;

            IScriptFactory f = exp.Clone() as IScriptFactory;
            f.CommandText.Append(' ');
            f.CommandText.Append(stringASC);

            return f;
        }

        public override IScriptFactory Descending(IScriptFactory exp)
        {
            if (exp == null)
                return this;

            IScriptFactory f = exp.Clone() as IScriptFactory;
            f.CommandText.Append(' ');
            f.CommandText.Append(stringDEC);

            return f;
        }

        public override IScriptFactory OrderBy(IScriptFactory exp)
        {
            if (exp == null)
                return this;

            IScriptFactory f = Clone() as IScriptFactory;
            f.CommandText.Append(' ');
            f.CommandText.Append(stringORDERBY);
            f.CommandText.Append(' ');
            f.CommandText.Append(exp.CommandText);
            f.Parameters.AddRange(exp.Parameters);

            return f;
        }

        #endregion

        #region Methods - Script - Join

        public override IScriptFactory Join(IScriptFactory target, IScriptFactory condition)
        {
            if (target == null || condition == null)
                return this;

            IScriptFactory f = Clone() as IScriptFactory;
            f.CommandText.Append(' ');
            f.CommandText.Append(stringJOIN);
            f.CommandText.Append(' ');
            f.CommandText.Append(target.CommandText);
            f.CommandText.Append(' ');
            f.CommandText.Append(stringON);
            f.CommandText.Append(' ');
            f.CommandText.Append(condition.CommandText);
            f.Parameters.AddRange(target.Parameters);
            f.Parameters.AddRange(condition.Parameters);

            return f;
        }

        public override IScriptFactory JoinLeft(IScriptFactory target, IScriptFactory condition)
        {
            if (target == null || condition == null)
                return this;

            IScriptFactory f = Clone() as IScriptFactory;
            f.CommandText.Append(' ');
            f.CommandText.Append(stringJOINLEFT);
            f.CommandText.Append(' ');
            f.CommandText.Append(target.CommandText);
            f.CommandText.Append(' ');
            f.CommandText.Append(stringON);
            f.CommandText.Append(' ');
            f.CommandText.Append(condition.CommandText);
            f.Parameters.AddRange(target.Parameters);
            f.Parameters.AddRange(condition.Parameters);

            return f;
        }

        #endregion

        #region Methods - Script - GroupBy

        public override IScriptFactory GroupBy(IScriptFactory exp)
        {
            if (exp == null)
                return this;

            IScriptFactory f = Clone() as IScriptFactory;
            f.CommandText.Append(' ');
            f.CommandText.Append(stringGroupBy);
            f.CommandText.Append(' ');
            f.CommandText.Append(exp.CommandText);
            f.Parameters.AddRange(exp.Parameters);

            return f;
        }

        #endregion

        #region Methods - Script - Edit

        public override IScriptFactory Insert(IScriptFactory target, DParameter[] parameters)
        {
            if (target == null || parameters == null || parameters.Length == 0)
                return this;

            IScriptFactory f = New();
            f.CommandText.Append(stringINSERT);
            f.CommandText.Append(' ');
            f.CommandText.Append(stringINTO);
            f.CommandText.Append(' ');
            f.CommandText.Append(target.CommandText);

            StringBuilder b1 = new StringBuilder();
            StringBuilder b2 = new StringBuilder();

            b1.Append('(' + FormatFieldName(parameters[0].Name));
            b2.Append('(' + parameters[0].ValueString);

            for (int i = 1; i < parameters.Length; i++)
            {
                b1.Append(string.Format(",{0}", FormatFieldName(parameters[i].Name)));
                b2.Append(string.Format(",{0}", parameters[i].ValueString));
            }

            b1.Append(')');
            b2.Append(')');

            f.CommandText.Append(' ');
            f.CommandText.Append(b1);
            f.CommandText.Append(' ');
            f.CommandText.Append(stringVALUES);
            f.CommandText.Append(' ');
            f.CommandText.Append(b2);
            f.Parameters.AddRange(target.Parameters);
            f.ExecuteArgument = eDbExecuteType.NonQuery;
            f.Type = eCommandType.Edit;

            return f;
        }

        public override IScriptFactory Update(IScriptFactory target, DParameter[] parameters)
        {
            if (target == null || parameters == null || parameters.Length == 0)
                return this;

            IScriptFactory f = New();
            f.CommandText.Append(stringUPADTE);
            f.CommandText.Append(' ');
            f.CommandText.Append(target.CommandText);
            f.CommandText.Append(' ');
            f.CommandText.Append(stringSET);

            StringBuilder b = new StringBuilder();

            b.Append(string.Format("{0} = {1}",
                FormatFieldName(parameters[0].Name), parameters[0].ValueString));

            for (int i = 1; i < parameters.Length; i++)
                b.Append(string.Format(", {0} = {1}",
                    FormatFieldName(parameters[i].Name), parameters[i].ValueString));

            f.CommandText.Append(' ');
            f.CommandText.Append(b);
            f.Parameters.AddRange(target.Parameters);
            f.ExecuteArgument = eDbExecuteType.NonQuery;
            f.Type = eCommandType.Edit;

            return f;
        }

        public override IScriptFactory Update(IScriptFactory target, IScriptFactory values)
        {
            if (target == null || values == null)
                return this;

            IScriptFactory f = New();
            f.CommandText.Append(stringUPADTE);
            f.CommandText.Append(' ');
            f.CommandText.Append(target.CommandText);
            f.CommandText.Append(' ');
            f.CommandText.Append(stringSET);
            f.CommandText.Append(' ');
            f.CommandText.Append(values.CommandText);

            f.Parameters.AddRange(target.Parameters);
            f.Parameters.AddRange(values.Parameters);
            f.ExecuteArgument = eDbExecuteType.NonQuery;
            f.Type = eCommandType.Edit;

            return f;
        }

        public override IScriptFactory Delete(IScriptFactory exp)
        {
            if (exp == null)
                return this;

            IScriptFactory f = New();
            f.CommandText.Append(stringDELETE);
            f.CommandText.Append(' ');
            f.CommandText.Append(exp.CommandText);
            f.Parameters.AddRange(exp.Parameters);
            f.ExecuteArgument = eDbExecuteType.NonQuery;
            f.Type = eCommandType.Edit;

            return f;
        }

        public override IScriptFactory Replace(IScriptFactory source, IScriptFactory target)
        {
            if (source == null || target == null)
                return this;

            IScriptFactory f = Clone() as IScriptFactory;
            f.CommandText.Insert(0, "REPLACE(");
            f.CommandText.Append(", ");
            f.CommandText.Append(source.CommandText);
            f.CommandText.Append(", ");
            f.CommandText.Append(target.CommandText);
            f.CommandText.Append(')');
            f.Parameters.AddRange(source.Parameters);
            f.Parameters.AddRange(target.Parameters);

            return f;
        }

        public override IScriptFactory Substring(IScriptFactory start, IScriptFactory count)
        {
            if (start == null || count == null)
                return this;

            IScriptFactory f = Clone() as IScriptFactory;
            f.CommandText.Insert(0, "SUBSTRING(");
            f.CommandText.Append(", ");
            f.CommandText.Append(start.CommandText);
            f.CommandText.Append(" + 1, ");
            f.CommandText.Append(count.CommandText);
            f.CommandText.Append(')');
            f.Parameters.AddRange(start.Parameters);
            f.Parameters.AddRange(count.Parameters);

            return f;
        }

        public override IScriptFactory ConvertToString()
        {
            IScriptFactory f = Clone() as IScriptFactory;
            f.CommandText.Insert(0, "CONVERT(nvarchar(max), ");
            f.CommandText.Append(", 23)");

            return f;
        }

        #endregion

        #endregion

        #region Methods - Expression

        public override IScriptFactory If(IScriptFactory condition, IScriptFactory ifTrue, IScriptFactory ifFalse)
        {
            if (condition == null || ifTrue == null || ifFalse == null)
                return this;

            IScriptFactory f = New();
            f.CommandText.Append("CASE WHEN (");
            f.CommandText.Append(condition.CommandText);
            f.CommandText.Append(") THEN (");
            f.CommandText.Append(ifTrue.CommandText);
            f.CommandText.Append(") ELSE (");
            f.CommandText.Append(ifFalse.CommandText);
            f.CommandText.Append(") END");

            f.Parameters.AddRange(condition.Parameters);
            f.Parameters.AddRange(ifTrue.Parameters);
            f.Parameters.AddRange(ifFalse.Parameters);

            return f;
        }

        public override IScriptFactory Equal(IScriptFactory exp)
        {
            if (exp == null)
                return this;

            IScriptFactory f = Clone() as IScriptFactory;
            if (exp.Parameters.Count > 0 && exp.Parameters[0].Value == null)
            {
                f.CommandText.Append(' ');
                f.CommandText.Append(stringIS);
                f.CommandText.Append(' ');
                f.CommandText.Append(stringNULL);
            }
            //else if (exp.Parameters.Count > 0 && exp.Parameters[0].Value is SqlGeometry)
            //{
            //    f.CommandText.Append(" equal to ");
            //    f.CommandText.Append(exp.CommandText);
            //}

            else
            {
                f.CommandText.Append(" = ");
                f.CommandText.Append(exp.CommandText);
            }

            f.Parameters.AddRange(exp.Parameters);

            return f;
        }

        public override IScriptFactory NotEqual(IScriptFactory exp)
        {
            if (exp == null)
                return this;

            IScriptFactory f = Clone() as IScriptFactory;
            if (exp.Parameters.Count > 0 && exp.Parameters[0].Value == null)
            {
                f.CommandText.Append(' ');
                f.CommandText.Append(stringIS);
                f.CommandText.Append(' ');
                f.CommandText.Append(stringNOT);
                f.CommandText.Append(' ');
                f.CommandText.Append(stringNULL);
            }
            else
            {
                f.CommandText.Append(" <> ");
                f.CommandText.Append(exp.CommandText);
            }

            f.Parameters.AddRange(exp.Parameters);

            return f;
        }

        public override IScriptFactory GreaterThan(IScriptFactory exp)
        {
            if (exp == null)
                return this;

            IScriptFactory f = Clone() as IScriptFactory;
            f.CommandText.Append(" > ");
            f.CommandText.Append(exp.CommandText);
            f.Parameters.AddRange(exp.Parameters);

            return f;
        }

        public override IScriptFactory GreaterThanOrEqual(IScriptFactory exp)
        {
            if (exp == null)
                return this;

            IScriptFactory f = Clone() as IScriptFactory;
            f.CommandText.Append(" >= ");
            f.CommandText.Append(exp.CommandText);
            f.Parameters.AddRange(exp.Parameters);

            return f;
        }

        public override IScriptFactory LessThan(IScriptFactory exp)
        {
            if (exp == null)
                return this;

            IScriptFactory f = Clone() as IScriptFactory;
            f.CommandText.Append(" < ");
            f.CommandText.Append(exp.CommandText);
            f.Parameters.AddRange(exp.Parameters);

            return f;
        }

        public override IScriptFactory LessThanOrEqual(IScriptFactory exp)
        {
            if (exp == null)
                return this;

            IScriptFactory f = Clone() as IScriptFactory;
            f.CommandText.Append(" <= ");
            f.CommandText.Append(exp.CommandText);
            f.Parameters.AddRange(exp.Parameters);

            return f;
        }

        public override IScriptFactory StartWith(IScriptFactory exp)
        {
            if (exp == null)
                return this;

            IScriptFactory f = Clone() as IScriptFactory;
            f.CommandText.Append(" LIKE ");
            f.CommandText.Append(exp.CommandText);
            f.CommandText.Append("+'%'");
            f.Parameters.AddRange(exp.Parameters);

            return f;
        }

        public override IScriptFactory EndWith(IScriptFactory exp)
        {
            if (exp == null)
                return this;

            IScriptFactory f = Clone() as IScriptFactory;
            f.CommandText.Append(" LIKE '%'+");
            f.CommandText.Append(exp.CommandText);
            f.Parameters.AddRange(exp.Parameters);

            return f;
        }

        public override IScriptFactory Contains(IScriptFactory exp)
        {
            if (exp == null)
                return this;

            IScriptFactory f = Clone() as IScriptFactory;
            f.CommandText.Append(" LIKE '%'+");
            f.CommandText.Append(exp.CommandText);
            f.CommandText.Append("+'%'");
            f.Parameters.AddRange(exp.Parameters);

            return f;
        }

        public override IScriptFactory And(IScriptFactory exp)
        {
            if (exp == null)
                return this;

            IScriptFactory f = Clone() as IScriptFactory;
            f.CommandText.Insert(0, '(');
            f.CommandText.Append(") AND (");
            f.CommandText.Append(exp.CommandText);
            f.CommandText.Append(')');
            f.Parameters.AddRange(exp.Parameters);

            return f;
        }

        public override IScriptFactory Or(IScriptFactory exp)
        {
            if (exp == null)
                return this;

            IScriptFactory f = Clone() as IScriptFactory;
            f.CommandText.Insert(0, '(');
            f.CommandText.Append(") OR (");
            f.CommandText.Append(exp.CommandText);
            f.CommandText.Append(')');
            f.Parameters.AddRange(exp.Parameters);

            return f;
        }

        #endregion

        #region Methods - Parameter

        public override DParameter CreateParameter()
        {
            return OnCreateParameter(OnCreateParameter());
        }

        protected virtual DbParameter OnCreateParameter()
        {
            return null;
        }

        protected virtual DParameter OnCreateParameter(DbParameter param)
        {
            return new DbCParameter(param);
        }

        #endregion

        #region Methods - Type

        public override eDataType GetDataType(string type)
        {
            if (string.IsNullOrWhiteSpace(type))
                throw new ArgumentNullException("type");

            eDataType dt = eDataType.Object;

            switch (type)
            {
                case "bit":
                    dt = eDataType.Boolean;
                    break;
                case "decimal":
                case "numeric":
                case "money":
                case "smallmoney":
                    dt = eDataType.Double;
                    break;
                case "real":
                case "float":
                    dt = eDataType.Float;
                    break;
                case "tinyint":
                    dt = eDataType.Byte;
                    break;
                case "smallint":
                    dt = eDataType.Int16;
                    break;
                case "int":
                    dt = eDataType.Int32;
                    break;
                case "bigint":
                    dt = eDataType.Int64;
                    break;
                case "nvarchar":
                case "text":
                case "ntext":
                case "varchar":
                case "nchar":
                case "xml":
                case "char":
                    dt = eDataType.String;
                    break;
                case "image":
                case "varbinary":
                case "binary":
                case "timestamp":
                    dt = eDataType.Binary;
                    break;
                case "uniqueidentifier":
                    dt = eDataType.Guid;
                    break;
                case "date":
                case "time":
                case "datetime2":
                case "datetimeoffset":
                case "smalldatetime":
                case "datetime":
                    dt = eDataType.DateTime;
                    break;
                //case "sql_variant":
                //    dt = eDataType.Object;
                //    break;
                //case "geometry":
                //    dt = eDataType.Geometry;
                //    break;
                default:
                    throw new NotSupportedException();
            }

            return dt;
        }

        public override string GetBooleanType(params object[] parameters)
        {
            return FormatFieldName("bit");
        }

        public override string GetFloatType(params object[] parameters)
        {
            return string.Format("{0}({1},{2})", FormatFieldName("decimal"), parameters[1], parameters[2]);
        }

        public override string GetDoubleType(params object[] parameters)
        {
            return string.Format("{0}({1},{2})", FormatFieldName("decimal"), parameters[1], parameters[2]);
        }

        public override string GetDecimalType(params object[] parameters)
        {
            return string.Format("{0}({1},{2})", FormatFieldName("decimal"), parameters[1], parameters[2]);
        }

        public override string GetByteType(params object[] parameters)
        {
            return FormatFieldName("tinyint");
        }

        public override string GetInt16Type(params object[] parameters)
        {
            return FormatFieldName("smallint");
        }

        public override string GetInt32Type(params object[] parameters)
        {
            return FormatFieldName("int");
        }

        public override string GetInt64Type(params object[] parameters)
        {
            return FormatFieldName("bigint");
        }

        public override string GetStringType(params object[] parameters)
        {
            int size = (int)parameters[0];
            string txt = size <= 0 ? "max" : size.ToString();

            return string.Format("{0}({1})", FormatFieldName("nvarchar"), txt);
        }

        public override string GetGuidType(params object[] parameters)
        {
            return FormatFieldName("uniqueidentifier");
        }

        public override string GetDateTimeType(params object[] parameters)
        {
            return FormatFieldName("datetime");
        }

        public override string GetObjectType(params object[] parameters)
        {
            return FormatFieldName("image");
        }

        public override string GetBinaryType(params object[] parameters)
        {
            int size = (int)parameters[0];
            if (size <= 0)
                return FormatFieldName("image");

            return string.Format("{0}({1})", FormatFieldName("binary"), parameters[0]);
        }

        public override string GetGeometryType(params object[] parameters)
        {
            return FormatFieldName("geometry");
        }

        #endregion

        #region Methods - Object

        public override IScriptFactory SchemaObject(string schema, string objName)
        {
            return Constant(schema).Stress().Concat(
                   Constant(objName).Stress(), ".");
        }

        public override IScriptFactory CreateObject(string schema, string objName, DataColumnAttribute[] cols)
        {
            IScriptFactory f = New();
            f.ExecuteArgument = eDbExecuteType.NonQuery;
            f.Type = eCommandType.Edit;
            f.CommandText.AppendFormat("CREATE TABLE {0} (", SchemaObject(schema, objName));

            DataColumnAttribute attr = cols[0];
            f.CommandText.Append(FormatProperty(attr).CommandText);

            for (int i = 1; i < cols.Length; i++)
            {
                attr = cols[i];
                f.CommandText.Append(", ");
                f.CommandText.Append(FormatProperty(attr).CommandText);
            }

            f.CommandText.Append(")");

            return f;
        }

        public override IScriptFactory DropObject(string schema, string objName)
        {
            IScriptFactory f = New();
            f.ExecuteArgument = eDbExecuteType.NonQuery;
            f.Type = eCommandType.Edit;
            f.CommandText.AppendFormat("DROP TABLE {0}", SchemaObject(schema, objName));

            return f;
        }

        public override IScriptFactory RenameObject(string schema, string objName, string objNameNew)
        {
            IScriptFactory f = New();
            f.ExecuteArgument = eDbExecuteType.NonQuery;
            f.Type = eCommandType.Edit;

            f.CommandText.AppendFormat("exec sp_rename '{0}','{1}'", objName, objNameNew);

            return f;
        }

        public override IScriptFactory CreateProperty(string schema, string objName, DataColumnAttribute col)
        {
            IScriptFactory f = New();
            f.ExecuteArgument = eDbExecuteType.NonQuery;
            f.Type = eCommandType.Edit;

            f.CommandText.AppendFormat(
                "ALTER TABLE {0} ADD {1}",
                SchemaObject(schema, objName), FormatProperty(col));

            return f;
        }

        public override IScriptFactory DropProperty(string schema, string objName, string colName)
        {
            IScriptFactory f = New();
            f.ExecuteArgument = eDbExecuteType.NonQuery;
            f.Type = eCommandType.Edit;

            f.CommandText.AppendFormat(
                "ALTER TABLE {0} DROP COLUMN {1}",
                SchemaObject(schema, objName), FormatFieldName(colName));

            return f;
        }

        public override IScriptFactory AlterProperty(string schema, string objName, DataColumnAttribute col)
        {
            IScriptFactory f = New();
            f.ExecuteArgument = eDbExecuteType.NonQuery;
            f.Type = eCommandType.Edit;

            f.CommandText.AppendFormat(
                "ALTER TABLE {0} ALTER COLUMN {1}",
                SchemaObject(schema, objName), FormatProperty(col));

            return f;
        }

        public override IScriptFactory FormatProperty(DataColumnAttribute col)
        {
            IScriptFactory f = New();
            f.CommandText.AppendFormat("{0} {1} {2}",
                FormatFieldName(col.ColumnName),
                GetDataType(col.ColumnType, col.Size, col.Precision, col.Scale),
                col.Nullable ? "NULL" : "NOT NULL");

            return f;
        }

        #endregion

        #endregion
    }
}
